package com.starview.star;

import com.starview.platform.data.EvaluationException;
import com.starview.platform.data.type.Location;
import com.starview.platform.data.value.ResourceURI;
import com.starview.platform.resource.ResourceException;
import com.starview.platform.resource.URIUtils;
import com.starview.platform.resource.catalog.Catalog;
import com.starview.platform.resource.catalog.CatalogException;
import com.starview.platform.resource.catalog.MemoryCatalog;
import com.starview.star.code.repository.CodeRepository;
import com.starview.star.compiler.ErrorReport;
import com.starview.star.compiler.ast.IAbstract;
import com.starview.star.compiler.format.Formatter;
import com.starview.star.compiler.grammar.OpGrammar;
import com.starview.star.compiler.operator.Operators;
import com.starview.star.compiler.standard.StandardNames;

import java.io.StringReader;

/**
 * Master access class for compiling and running StarRules programs
 *
 * @author fgm
 */
public class StarRules{
  /**
   * Main command-line entry point for the Star compiler
   *
   * @param source url
   * @param args   run time arguments
   * @throws LanguageException
   * @throws EvaluationException
   */
  public static ErrorReport compileAndGo(String source, String args[]) throws LanguageException, EvaluationException{
    return StarMain.compileAndGo(source, args);
  }

  public static String format(CodeRepository repository, ResourceURI uri, Catalog catalog, ErrorReport errors)
          throws LanguageException, ResourceException, CatalogException{
    try {
      return Formatter.formatSource(uri, errors, StandardNames.PACKAGE, repository, catalog);
    } catch (Exception e) {
      errors.reportError("problem in formatting ", Location.location(uri));
      return null;
    }
  }

  public static IAbstract parseString(String text, Location loc, ErrorReport errors){
    OpGrammar parser = new OpGrammar(Operators.operatorRoot(), errors);

    return parser.parse(loc.getUri(), new StringReader(text), loc);
  }

  public static void main(String args[]){
    if (args.length > 0) {
      try {
        String nArgs[] = new String[args.length - 1];
        for (int ix = 0; ix < nArgs.length; ix++)
          nArgs[ix] = args[ix + 1];
        ErrorReport report = compileAndGo(args[0], nArgs);
        System.err.print(report);
      } catch (LanguageException e) {
        System.err.println("Compile errors in " + args[0] + "\n" + e.getMessages().toString());
      } catch (EvaluationException e) {
        System.err.println("Run-time error in " + args[0] + "\n" + e.getMessage() + " at " + e.getLoc());
      }
    } else
      System.err.println("usage: <> sourceFile");
  }

  public static Catalog starCatalog(){
    Catalog cat = new MemoryCatalog("star", URIUtils.create("star", "."));

    try {
      cat.addEntry("base", URIUtils.parseUri("std:base.star"));
      cat.addEntry("validate", URIUtils.parseUri("std:validate.star"));
      cat.addEntry("compute", URIUtils.parseUri("std:compute.star"));
      cat.addEntry("maybe", URIUtils.parseUri("std:maybe.star"));
      cat.addEntry("monad", URIUtils.parseUri("std:monad.star"));
      cat.addEntry("star", URIUtils.parseUri("std:star.star"));
      cat.addEntry("sequences", URIUtils.parseUri("std:sequences.star"));
      cat.addEntry("arithmetic", URIUtils.parseUri("std:arithmetic.star"));
      cat.addEntry("iterators", URIUtils.parseUri("std:iterators.star"));
      cat.addEntry("casting", URIUtils.parseUri("std:casting.star"));
      cat.addEntry("bitstring", URIUtils.parseUri("std:bitstring.star"));
      cat.addEntry("treemap", URIUtils.parseUri("std:treemap.star"));
      cat.addEntry("arraymap", URIUtils.parseUri("std:arraymap.star"));
      cat.addEntry("arrays", URIUtils.parseUri("std:arrays.star"));
      cat.addEntry("altarrays", URIUtils.parseUri("std:altarrays.star"));
      cat.addEntry("maps", URIUtils.parseUri("std:maps.star"));
      cat.addEntry("relations", URIUtils.parseUri("std:relations.star"));
      cat.addEntry("indexed", URIUtils.parseUri("std:indexed.star"));
      cat.addEntry("queue", URIUtils.parseUri("std:queue.star"));
      cat.addEntry("cons", URIUtils.parseUri("std:cons.star"));
      cat.addEntry("actors", URIUtils.parseUri("std:actors.star"));
      cat.addEntry("macrosupport", URIUtils.parseUri("std:macrosupport.star"));
      cat.addEntry("dequote", URIUtils.parseUri("std:dequote.star"));
      cat.addEntry("formatter", URIUtils.parseUri("std:formatter.star"));
      cat.addEntry("fileio", URIUtils.parseUri("std:fileio.star"));
      cat.addEntry("dateNtime", URIUtils.parseUri("std:dateNtime.star"));
      cat.addEntry("iterable", URIUtils.parseUri("std:iterable.star"));
      cat.addEntry("updateable", URIUtils.parseUri("std:updateable.star"));
      cat.addEntry("finger", URIUtils.parseUri("std:finger.star"));
      cat.addEntry("fingerPrelude", URIUtils.parseUri("std:fingerPrelude.star"));
      cat.addEntry("utils", URIUtils.parseUri("std:utils.star"));
      cat.addEntry("strings", URIUtils.parseUri("std:strings.star"));
      cat.addEntry("folding", URIUtils.parseUri("std:folding.star"));
      cat.addEntry("threads", URIUtils.parseUri("std:threads.star"));
      cat.addEntry("task", URIUtils.parseUri("std:task.star"));
      cat.addEntry("cml0", URIUtils.parseUri("std:cml0.star"));
      cat.addEntry("cml", URIUtils.parseUri("std:cml.star"));
      cat.addEntry("cmlSpinLock", URIUtils.parseUri("std:cmlSpinLock.star"));
      cat.addEntry("cmlAtomicRef", URIUtils.parseUri("std:cmlAtomicRef.star"));
      cat.addEntry("cmlQueue", URIUtils.parseUri("std:cmlQueue.star"));
      cat.addEntry("fibers", URIUtils.parseUri("std:fibers.star"));
      cat.addEntry("concurrency", URIUtils.parseUri("std:concurrency.star"));
      cat.addEntry("custodians", URIUtils.parseUri("std:custodians.star"));
    } catch (Exception e) {
      e.printStackTrace();
    }
    return cat;
  }
}
